package com.spzx.product.service.impl;

import com.spzx.product.api.domin.ProductSku;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.query.SkuQuery;
import com.spzx.product.service.ProductSkuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.vo.ProductSkuVo;
import com.spzx.product.vo.SkuPriceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品sku 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2025-04-28
 */
@Slf4j
@Service
public class ProductSkuServiceImpl extends ServiceImpl<ProductSkuMapper, ProductSku> implements ProductSkuService {
    @Autowired

    private RedisTemplate redisTemplate;
    @Override
    public List<ProductSkuVo> selectTopSale() {
        return baseMapper.selectTopSale();
    }

    @Override
    public List<ProductSkuVo> getskulist(SkuQuery skuQuery) {
        return baseMapper.getskulistvo(skuQuery);
    }

    @Override
    public ProductSku getinfo(Long skuId) {
        //1先从redis中获取数据
        //1.1构建业务数据缓存
        String datakey = "sku:info"+skuId;
        //1.2查询redis缓存数据
        ProductSku productSku = (ProductSku) redisTemplate.opsForValue().get(datakey);
        //1.3查询有结果返回
        if(productSku!=null){
            return productSku;
        }
        //2尝试获取锁
        //2.1构建锁
        String lockName = datakey+":lock";
        //2.2构建当前线程唯一标识\
        String lockValue= UUID.randomUUID().toString();
        //2.3尝试获取锁
        Boolean b = redisTemplate.opsForValue().setIfAbsent(lockName, lockValue, 5, TimeUnit.SECONDS);
        if (b){
            try {
                //3.1查数据库
                productSku = getById(skuId);
                //3.2 缓存数据到Redis中
                //3.2 设置过期时间 基础时间+随机时间 避免群体key失效，缓存雪崩现象之一
                int ttl=3600+new Random().nextInt(600);
                redisTemplate.opsForValue().set(datakey,productSku,ttl,TimeUnit.SECONDS);
                return productSku;
            } finally {
                String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                        "then\n" +
                        "    return redis.call(\"del\",KEYS[1])\n" +
                        "else\n" +
                        "    return 0\n" +
                        "end\n";
                RedisScript<Boolean> booleanRedisScript = new DefaultRedisScript<>(script, Boolean.class);
                redisTemplate.execute(booleanRedisScript, Arrays.asList(lockName), lockValue);
            }
        }else {
            log.error("获取锁失败尝试自旋", Thread.currentThread().getName());
            return this.getinfo(skuId);
        }
    }


    @Override
    public SkuPriceVo getskuprice(Long skuId) {
        //为价格赋值
        LambdaQueryWrapper<ProductSku> productSkuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        productSkuLambdaQueryWrapper.eq(ProductSku::getId,skuId);
        productSkuLambdaQueryWrapper.select(ProductSku::getSalePrice,ProductSku::getMarketPrice);
        ProductSku productSku = baseMapper.selectOne(productSkuLambdaQueryWrapper);
        if (productSku!=null){
            SkuPriceVo skuPriceVo = new SkuPriceVo();
            skuPriceVo.setSkuId(skuId);
            skuPriceVo.setSalePrice(productSku.getSalePrice());
            skuPriceVo.setMarketPrice(productSku.getMarketPrice());
            return  skuPriceVo;
        }
        return null;
    }

    @Override
    public Map<String, Long> getskuspecvalue(Long productId) {
        //1创建保存映射关系map
        HashMap<String, Long> spcmap = new HashMap<>();
        //2根据商品id查询商品sku列表
        LambdaQueryWrapper<ProductSku> productSkuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        productSkuLambdaQueryWrapper.eq(ProductSku::getProductId,productId);
        productSkuLambdaQueryWrapper.select(ProductSku::getSkuSpec,ProductSku::getId);
        List<ProductSku> productSkuList = list(productSkuLambdaQueryWrapper);
        //3遍历sku表将sku参数跟skuid封装到map中
        if (!CollectionUtils.isEmpty(productSkuList)){
            for (ProductSku sku : productSkuList) {
                spcmap.put(sku.getSkuSpec(),sku.getId());
            }
        }
        return spcmap;
    }

    @Override
    public List<SkuPriceVo> getskupricelist(List<Long> skuIds) {
        LambdaQueryWrapper<ProductSku> productSkuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        productSkuLambdaQueryWrapper.in(ProductSku::getId,skuIds);
        productSkuLambdaQueryWrapper.select(ProductSku::getSalePrice,
                                            ProductSku::getMarketPrice,
                                            ProductSku::getId);
        List<ProductSku> productSkus = list(productSkuLambdaQueryWrapper);
        //将sku对象封装到vo中
        if (!ObjectUtils.isEmpty(productSkus)){
            List<SkuPriceVo> skuPriceVos = productSkus.stream()
                    .map(productSku -> {
                        SkuPriceVo skuPriceVo = new SkuPriceVo();
                        skuPriceVo.setSkuId(productSku.getId());
                        skuPriceVo.setSalePrice(productSku.getSalePrice());
                        skuPriceVo.setMarketPrice(productSku.getMarketPrice());
                        return skuPriceVo;
                    }).collect(Collectors.toList());
            return skuPriceVos;
        }
        return null;
    }
}
